﻿package fab.graphics
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.FrameLabel;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.filters.*;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.ApplicationDomain;
	import flash.utils.clearInterval;
	import flash.utils.getQualifiedClassName;
	import flash.utils.setInterval;
	import flash.utils.setTimeout;
	import flash.utils.Timer;
	import jeusurf.movies.Tunnel;
	
	
	public class BitmapMovieClip extends Sprite 
	{		
		public var bmp:Bitmap;
		public var frames:Array;
		private var displayBitmapData:BitmapData;
		private var embed:MovieClip;
		private var _currentFrame:int = 0;
		private var sourceRect:Rectangle;
		private var sens:Boolean=true;
		private var scripts:Array = new Array();
		private var scripts_args:Array = new Array();
		private var _currentLabels:Array;
		private var slowdown_iv:int;
		
		public function BitmapMovieClip( _embed:MovieClip, parsingNow:Boolean = true )
		{
			embed = _embed;
			sourceRect = _embed.getBounds(_embed);
			_currentLabels = embed.currentLabels;
			displayBitmapData = new BitmapData( sourceRect.width, sourceRect.height, true, 0 );
			bmp = new Bitmap( displayBitmapData, "auto", true );
			addChild( bmp );	
			frames = new Array();
			if ( parsingNow )
			{
				parse_frames();
				gotoAndStop( 1 );	
			}
			else {
			}
		}
		private function parse_frames():void
		{
			for ( var f:int = 1; f <= embed.totalFrames; f++ )// test opti
			{
				embed.gotoAndStop( f );
				var bmp:BitmapData = new BitmapData( embed.width, embed.height, true, 0x000000 );
				bmp.draw( embed );
				frames.push( bmp.clone() );
			}
		}			
		private function print( scale:Number=1 ):void 
		{
			//var mat:Matrix = new Matrix();
			//mat.scale( scale, scale );
			
			var topleft:Point = new Point();
			//var topleft:Point = point.subtract( new Point( half_boule * scale, half_boule * scale ) );

			displayBitmapData.fillRect( sourceRect, 0 );
			displayBitmapData.copyPixels( frames[ _currentFrame ], sourceRect, topleft , null, null, true );
			
			if ( scripts[ _currentFrame ] is Function )
			{
				var func:Function = scripts[ _currentFrame ];
				var args:Array;
				if ( scripts_args[ _currentFrame ] )
				{
					args = scripts_args[ _currentFrame ];
					func.call( this, args );
				}
				else {
					func();
				}
			}
			//trace("print",_currentFrame );
		}
		private function enter_frame(e:Event):void 
		{
			if ( sens ) nextFrame(); else prevFrame();
		}
		public function slowdown(d:Number=50):void
		{
			stop();
			slowdown_iv = setInterval( nextFrame, d );
		}

	/// The MovieClip class inherits from the following classes: Sprite, DisplayObjectContainer, InteractiveObject, DisplayObject, and EventDispatcher.
		/// Specifies the number of the frame in which the playhead is located in the timeline of the MovieClip instance.
		public function get currentFrame () : int
		{
			return _currentFrame + 1;
		}

		// Returns an array of FrameLabel objects from the current scene.
		public function get currentLabels () : Array
		{
			return _currentLabels;
		}
		

		/// The total number of frames in the MovieClip instance.
		public function get totalFrames () : int
		{
			return frames.length;
		}

		/// [Undocumented] Takes a collection of frame (zero-based) - method pairs that associates a method with a frame on the timeline.
		public function addFrameScript (frame:int, method:Function, ...rest ) : void
		{
			scripts[ frame ] = method;
			if ( rest.length > 0 ) scripts_args[ frame ] = rest;
		}
		
		/// Starts playing the SWF file at the specified frame.
		public function gotoAndPlayReverse (frame:Object, scene:String = null) : void
		{
			sens = false;
			goto( frame );
			addEventListener(Event.ENTER_FRAME, enter_frame );
		}
		public function gotoAndPlay (frame:Object, scene:String = null) : void
		{
			sens = true;
			goto( frame );
			addEventListener(Event.ENTER_FRAME, enter_frame );
		}
		
		private function goto(frame:Object):void
		{
			if ( frame is String )
			{
				for (var i:uint = 0; i < _currentLabels.length; i++) {
					var label:FrameLabel = _currentLabels[i];
					//trace("frame " + label.frame + ": " + label.name);
					if ( label.name == frame )
					{
						_currentFrame = label.frame - 1;
						break;
					}
				}
			}
			else _currentFrame = int( frame ) - 1;
		}
		
		/// Brings the playhead to the specified frame of the movie clip and stops it there.
		public function gotoAndStop (frame:Object, scene:String = null) : void
		{
			stop();
			if ( frame is String ) _currentFrame = _currentLabels[ frame ];
			else _currentFrame = int( frame ) - 1;			
			print();
		}

		/// Sends the playhead to the next frame and stops it.
		public function nextFrame (e:*=null) : void
		{
			_currentFrame = ( _currentFrame + 1 ) % frames.length;
			print();
		}
		/// Moves the playhead in the timeline of the movie clip.
		public function play () : void
		{
			clearInterval( slowdown_iv );
			sens = true;
			addEventListener(Event.ENTER_FRAME, enter_frame )
		}
		/// Sends the playhead to the previous frame and stops it.
		public function prevFrame () : void
		{
			_currentFrame = ( _currentFrame - 1 + totalFrames ) % totalFrames;
			print();
		}
		/// Stops the playhead in the movie clip.
		public function stop () : void
		{
			removeEventListener(Event.ENTER_FRAME, enter_frame );
		}
		public function clone () : *
		{
			var classe:Class = ApplicationDomain.currentDomain.getDefinition( getQualifiedClassName( this )) as Class;
			var bmpmc:* = new classe( embed, false );
			bmpmc.frames = new Array();
			for each( var bm:BitmapData in frames ) bmpmc.frames.push( bm );// .clone() );
			return bmpmc;
		}		
		
		/*
		/// Moves the playhead to the previous scene of the MovieClip instance.
		public function prevScene () : void
		{
			
		}
		/// The current label in which the playhead is located in the timeline of the MovieClip instance.
		public function get currentLabel () : String;
		{
			
		}
		/// The current scene in which the playhead is located in the timeline of the MovieClip instance.
		public function get currentScene () : Scene
		{
			
		}
		/// A Boolean value that indicates whether a movie clip is enabled.
		public function get enabled () : Boolean
		{
			
		}		
		public function set enabled (value:Boolean) : void
		{
			
		}
		/// The number of frames that are loaded from a streaming SWF file.
		public function get framesLoaded () : int
		{
			
		}
		/// An array of Scene objects, each listing the name, the number of frames, and the frame labels for a scene in the MovieClip instance.
		public function get scenes () : Array
		{
			
		}
		/// Moves the playhead to the next scene of the MovieClip instance.
		public function nextScene () : void
		{
			
		}		
		*/
	}
}